package clientConnexion;
import java.applet.*;
import java.net.*;
import java.util.LinkedList;
import java.io.*;

//******************************************************************************
// Client.java
// E.Lefran�ois 10 f�vrier 2001
// Projet "Chat", avec soquettes
//******************************************************************************

//==============================================================================
// classe "FenetreApplication"
// -->  Support pour l'application ex�cut�e en mode "Standalone"  (Application
// autonome)
//
// Cette classe agit en tant que fen�tre "top level" dans laquelle s'ex�cute
// l'applet.
//==============================================================================


//==============================================================================
// Classe Client
// Attend des �v�nements utilisateurs:
//        1) "connecter":  demande de connexion demand�e par l'utilisateur
//        2) "envoyer": un message doit �tre envoy� aux autres clients
//        3) "deconnecter":  demande de d�connexion demand�e par l'utilisateur
//
// Attend des �v�nements g�n�r�s par le serveur
//        1) "sessionAcceptee": la demande de session a �t� accept�e
//        3) "sessionRefusee": la demande de session a �t� refus�e
//        2) "connexionFermee": la connexion est termin�e, et la session par
//            la m�me occasion
//            Causes possibles (non distingu�es)
//                - Normale: suite � demande de d�connexion demand�e par
//                  l'utilisateur
//                - Anormale:  le serveur est "tomb�", probl�me d'I/O
//
// En r�ponse � une demande de connexion de l'utilisateur:
// 1/ une socket est cr��e afin de pouvoir communiquer avec le serveur.
// 2/ le programme cr�e une instance de la classe "Connexion", un objet
//    actif qui sera responsable de la r�ception et de l'analyse des messages
//    envoy�s par le serveur.
//
// En r�ponse � une demande d'envoi, la ligne de texte sp�cifi�e par
// l'utilisateur est envoy�e au serveur.
//
// En r�ponse � une demande de d�connexion, ou lorsque l'application est
// "quitt�e", le message de fin de session est envoy� au serveur.  C'est le
// serveur lui-m�me qui fermera la socket.
//==============================================================================

//------------------------------------------------------------------------------
//public class Client extends Applet {
public class Client extends Applet {	
/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	// Constantes de classes
	private static final int NO_PORT = 5002;    // No du port attache au serveur
	// Variables d'instance

	private boolean connexionEnCours = false;
	//private boolean sessionEnCours = false;
	private String monId ="";    // Identificateur du client

	//private boolean standAloneMode = false;
	// Si true: execution en tant qu'application "standalone"
	// Si false: execution en tant qu'applet

	/**
	 * @link aggregationByValue 
	 */
	//private InterfaceUtilisateur gui;
	// Definition de l'interface utilisateur (boutons, ..)


	/**
	 * @supplierRole socket
	 * @link aggregationByValue 
	 */
	private Socket socket;
	// socket connectee au serveur


	/**
	 * @supplierRole ecouteurDuServeur
	 * @link aggregationByValue 
	 */
	//private ServeurEcouteur ecouteurDuServeur;
	// Objet actif associe, qui ecoute le serveur de maniere
	// concurrente au reste du programme


	/**
	 * @supplierRole canalDeSortie 
	 */
	// Canal de sortie
	private ObjectOutputStream canalSeSortie;

	private ServeurEcouteur serveurEcouteur;

	// Constructeur(s)
	public Client() {
	}

	public void init() {
		// Methode appelee lorsque l'applet est chargee pour la premiere fois, ou
		// lorsqu'elle est rechargee.
		// Cette methode est utilisee pour operer diverses initialisations
		// (structures de donnees, composants de la fenetre, ..)
	}

	public void start() {
		// Methode appelee lorsque l'applet est initialisee (suit le message init()),
		// et a chaque fois que la page qui contient l'applet est a nouveau activee
		if (! connexionEnCours) demarrerSession();
	}

	public void stop(){}
	// Methode appelee lorsque la page qui contient l'applet est desactivee
	// Le chat continue en arriere plan

	public void ev_connexionFermee (String message) {
		// Evenement envoye par l'ecouteur du serveur
		System.out.println("Connexion terminee");
		fermerSession();
	}

	// Gestion des �v�nements


	public void ev_play() {
		envoyerTexteAuServeur("#CTR#START");
	}
	
	public void ev_stop() {
		envoyerTexteAuServeur("#CTR#STOP");
	}
	
	public boolean ev_pass() {
		envoyerTexteAuServeur("#CTR#PASS");
		serveurEcouteur.setEnTransition(true);
		while(serveurEcouteur.estEntransition()) {
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return true;
	}
	
	public void ev_load() {
		envoyerTexteAuServeur("#CTR#LOAD");
	}
	
	public void ev_load_genre(LinkedList<String> list) {
		String s = "#CTR#LOAD_GENRE";
		for (int i = 0; i < list.size(); i++) {
			s += "#";
			s += list.get(i);
		}
		envoyerTexteAuServeur(s);
	}
	
	public LinkedList<String> ev_getGenre() {
		ev_connecter();
		LinkedList<String> result;
		envoyerTexteAuServeur("#GET#GENRE");
		while(!serveurEcouteur.isGenreAJour()) {
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		result = serveurEcouteur.getGenre();
		serveurEcouteur.setGenreAJour(false);
		return result;
		
	}
	
	public void ev_connecter () {
		// Demande de connexion demandee par le client
		demarrerSession();
	}

	public void ev_deconnecter () {
		// Fin de connexion demandee par le client
		seDeconnecter();

	}

	public void ev_envoyer(String s) {
		if (s.length()!=0)
			//envoyerTexteAuServeur("#DATA#"+gui.getMessage()); 
			envoyerTexteAuServeur(s); // Test pour sheepMIx.
	}

	// Evenements
	public void ev_sessionAcceptee() {
		// Evenement envoye par le serveur (Via ecouteur de serveur)
		//sessionEnCours = true;
		//gui.activerEnvoi();
	}

	public void ev_sessionRefusee(String message) {
		// Evenement envoye par le serveur (Via ecouteur de serveur)
		//gui.afficherAvertissement("!! SESSION REFUSEE !! ", message);
		seDeconnecter();
	}

	// Methodes diverses
	public String getIdClient () {return monId; }
	public void setIdClient(String id) {monId = id; }

	// Methodes privees
	private void envoyerTexteAuServeur (String text) {
		if (! connexionEnCours) return;
		String t = text.replace('\n',(char)0);
		try {
			canalSeSortie.writeObject(t);
			canalSeSortie.flush();// le canal a ete cree sans  "automatic flush"
		}
		catch (Exception e) {
			//gui.afficherAvertissement
			//("!! PROBLEME DE CONNEXION !! " , e.toString());
			fermerSession();
		}
	}

	private String saisirIdentificateurClient () {
		monId = "sheepGUI";
		//LoginDialogue ld = new LoginDialogue ((Frame)getParent(), this);
		//ld.show();
		return monId;
	}

	private void demarrerSession() {
		System.out.println("Demarrer Session");
		String id = saisirIdentificateurClient();
		if (id != null) {
			connexionEnCours = seConnecter();
			if (connexionEnCours) {
				//gui.activerEtatConnexion();
				envoyerTexteAuServeur("#CTR#LOGIN#"+id);
			}
		}
	}

	private void fermerSession() {
		connexionEnCours = false;
		//sessionEnCours = false;
		if (socket != null)
			try {socket.close();} catch (IOException e ) {}
	}

	private void seDeconnecter() {
		if (connexionEnCours) {    // Programmation defensive
			envoyerTexteAuServeur ("#CTR#LOGOUT");
		}
	}

	private boolean seConnecter () {
		// Retourne "true" si la connexion est etablie, "false" dans les autres cas
		if (connexionEnCours) return true;

		InetAddress adresseIP;
		//------------ Essayer l'adresse
		try {
//			adresseIP = InetAddress.getByName("192.168.1.19");
			//adresseIP = InetAddress.getByName("192.168.55.5");
			adresseIP = InetAddress.getLocalHost();   // Connexion en local
			//System.out.println( adresseIP.getHostAddress());
			//System.out.println( adresseIP.getHostName());
		}
		catch (UnknownHostException e) {
			System.out.println("Probleme de connexion");
			return false;
		}
		//------------- Creation de la socket permettant de communiquer avec
		//              le serveur
		try {
			socket = new Socket (adresseIP, NO_PORT);
		}
		catch (IOException e) {
			System.out.println("Probleme de connexion");
			return false;
		}
		//------------- Ouverture des canaux d'entr�e et de sortie
		try {
			canalSeSortie = new ObjectOutputStream
					(socket.getOutputStream());
			serveurEcouteur = new ServeurEcouteur
					(socket.getInputStream(),this);

			return true;    // Connexion OK
		}
		catch (IOException e) {
			try {socket.close(); } catch (IOException ioe) {};
			System.out.println("Probleme de connexion");
			return false;
		}
	}
}

